﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Threading;

namespace 时间转换
{
    public class DateTimeConvert
    {
        
        #region  DateTime
        /// <summary>
        /// trick==>Datetime
        /// </summary>
        /// <param name="trick"></param>
        /// <returns></returns>
        public static DateTime Converter(long trick)
        {
            return new DateTime(trick);
        }
        /// <summary>
        /// span==>Datetime
        /// </summary>
        /// <param name="span"></param>
        /// <returns></returns>
        public static DateTime Converter(TimeSpan span)
        {
            return new DateTime(span.Ticks);
        }
        /// <summary>
        /// DateTime==>TimeSpan
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static TimeSpan Converter(DateTime time)
        {
            return new TimeSpan(time.Ticks);
        }
        /// <summary>
        /// 转化为Localtime
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static DateTime ConvertToLocal(DateTime time)
        {
            return time.ToLocalTime();
        }
        /// <summary>
        /// 时间转化为Universaltime
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static DateTime ConvertToUniversal(DateTime time)
        {
            return time.ToUniversalTime();
        }
        #endregion
        #region  DateTimeOffset=DateTime+offset (只是时间偏移量不能确定时区和夏令时)
        /// <summary>
        /// 如果 DateTime.Kind 的值为 DateTimeKind.Utc，则新实例的 DateTime 属性被设置为 dateTime，Offset 属性被设置为 Zero。
        /// 如果 DateTime.Kind 的值为 DateTimeKind.Local 或 DateTimeKind.Unspecified，则新实例的 DateTime 属性被设置为 dateTime，Offset 属性被设置为本地系统当前时区的偏移量。
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns> 
        public static DateTimeOffset CreateDateTimeOffset(DateTime time)
        {
            return new DateTimeOffset(time);
        }
        public static DateTimeOffset CreateDateTimeOffset(DateTime time,TimeSpan span)
        {
            return new DateTimeOffset(time, span);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="trick"></param>
        /// <param name="span">相对于utc的时间偏移量</param>
        /// <returns></returns>
        public static DateTimeOffset CreateDateTimeOffset(long trick,TimeSpan span)
        {
            return new DateTimeOffset(trick ,span );
        }
        public static DateTimeOffset CreateDateTimeOffset(int year, int month, int day, int hour, int minute, int second, TimeSpan offset)
        {
            return new DateTimeOffset(year, month, day, hour, minute, second, offset);
        }
        #endregion
        #region  时间转化的核心函数在TimeZoneInfo
        /// <summary>
        /// 根据DateTimeKind值将Time转化为目的时区的值。 DateTimeKind.Unspecified默认为DateTimeKind.Local
        /// </summary>
        /// <param name="time"></param>
        /// <param name="?"></param>
        /// <returns></returns>
        public static DateTime ConvertToSpecialTime(DateTime time,TimeZoneInfo zoneInfo)
        {
            return TimeZoneInfo.ConvertTime(time, zoneInfo);
        }
        /// <summary>
        /// DateTimeKind.Unspecified的DateTime必须根据特定时区才能判定时间
        /// </summary>
        public static void OutputSpcialTimeKind()
        {
            TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
            var time = DateTimeConvert.ConvertToSpecialTime(DateTime.Now, zone);
            Console.WriteLine(time.Kind.ToString());
        }
        /// <summary>
        /// 将srcZone的时间转化为目的时区的时间。
        /// </summary>
        /// <param name="srcTime"></param>
        /// <param name="srcZone"></param>
        /// <param name="desZone"></param>
        /// <returns></returns>
        public static DateTime ConvertSpecialTimeToSpecialTime(DateTime srcTime, TimeZoneInfo srcZone,  TimeZoneInfo desZone)
        {
            return TimeZoneInfo.ConvertTime(srcTime, srcZone, desZone);
        }
        /// <summary>
        /// 根据时区ID进行时区转化： ZoneId 必须是系统的，自定义不行
        /// </summary>
        /// <param name="srcTime"></param>
        /// <param name="srcZoneId"></param>
        /// <param name="desZoneId"></param>
        /// <returns></returns>
        public static DateTime ConvertSpecialTimeToSpecialTimeByZoneId(DateTime srcTime, string srcZoneId, string desZoneId)
        {
            return TimeZoneInfo.ConvertTimeBySystemTimeZoneId(srcTime, srcZoneId, desZoneId);
        }
        /// <summary>
        /// 查看系统时区及是否有夏令时规则
        /// </summary>
        public static void IsDayLightTimeZone()
        {
            foreach (var zone in TimeZoneInfo.GetSystemTimeZones())
            {
                Console.WriteLine("TimeZone{0} SupportDaylightSavingTime:{1}", zone.DisplayName, zone.SupportsDaylightSavingTime);
            }
        }

        #region  自定义时区 （有夏令时规则不一定支持夏令时）
        public static TimeZoneInfo CreateFixedTimeRuleTimeZone()
        {
            TimeSpan span = new TimeSpan(1, 30, 0);
            TimeZoneInfo.TransitionTime start = TimeZoneInfo.TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1, 17, 0, 0), 3, 15);
            TimeZoneInfo.TransitionTime end = TimeZoneInfo.TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1, 23, 0, 0), 11, 25);
            List<TimeZoneInfo.AdjustmentRule> adjustmentList = new List<TimeZoneInfo.AdjustmentRule>();
            TimeZoneInfo.AdjustmentRule adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(2012, 1, 1), new DateTime(2012, 12, 31), span, start, end);
            adjustmentList.Add(adjustment);
            TimeZoneInfo myTimeZone = TimeZoneInfo.CreateCustomTimeZone("MyTimeZOne", new TimeSpan(8, 0, 0),
                             "(GMT+08:00) Fictitious Time", "Fictitious Standard Time",
                             "Fictitious Daylight Time", adjustmentList.ToArray());
            return myTimeZone; 
        }
        public static TimeZoneInfo CreateFloatingTimeRuleTimeZone()
        {
            TimeSpan span = new TimeSpan(1, 0, 0);
            TimeZoneInfo.TransitionTime start = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 2, 0, 0), 3, 5, DayOfWeek.Sunday);
            TimeZoneInfo.TransitionTime end = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 3, 0, 0), 10, 4, DayOfWeek.Sunday);   
            List<TimeZoneInfo.AdjustmentRule> adjustmentList = new List<TimeZoneInfo.AdjustmentRule>();
            TimeZoneInfo.AdjustmentRule adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(2012, 1, 1), new DateTime(2012, 12, 31), span, start, end);
            adjustmentList.Add(adjustment);
            TimeZoneInfo myTimeZone = TimeZoneInfo.CreateCustomTimeZone("MyTimeZOne", new TimeSpan(8, 0, 0),
                             "(GMT+08:00) Fictitious Time", "Fictitious Standard Time",
                             "Fictitious Daylight Time", adjustmentList.ToArray());
            return myTimeZone; 
        }
        #endregion
        #endregion
        #region string==>Datetime
        /// <summary>
        /// 
        /// </summary>
        /// <param name="timeFormat"></param>
        /// <returns></returns>
        public static DateTime ConverterStringToTime(string timeFormat)
        {
            DateTime time;
            bool result = DateTime.TryParse(timeFormat, out time);
            return time;
        }
        /// <summary>
        /// 根据Culture 和 timeFormat转化时间
        /// </summary>
        /// <param name="timeFormat"></param>
        /// <param name="provider"></param>
        /// <param name="styles"></param>
        /// <returns></returns>
        public static DateTime ConverterStringToTime(string timeFormat, IFormatProvider provider, DateTimeStyles styles)
        {
            if (provider == null)
            {
                provider = CultureInfo.CurrentCulture;
            }
            DateTime time;
            bool result = DateTime.TryParse(timeFormat, provider, styles, out time);
            return time;
        }
        #endregion
        #region  DateTime==>String   慎用DateTime 的ToXXstring()
        /// <summary>
        /// 默认cultrue下，tostring输出结果
        /// </summary>
        /// <param name="time"></param>
        public static void DateTimeDefaultString()
        {
            Console.WriteLine(DateTime.Now.ToShortDateString());
            Console.WriteLine(DateTime.Now.ToShortTimeString());
            Console.WriteLine(DateTime.Now.ToString());
            Console.WriteLine(DateTime.Now.ToLongTimeString());
            Console.WriteLine(DateTime.Now.ToLongDateString());
        }
        #region DateTimeFormatInfo.InvariantInfo 用法举例
        public static void DateTimeDefaultStringInDifferentCulture1()
        {
            foreach (var culture in CultureInfo.GetCultures(CultureTypes.WindowsOnlyCultures))
            {

                Thread.CurrentThread.CurrentCulture = culture;
                Console.WriteLine(DateTime.Now.ToString("d"));
            }
        }
        public static void DateTimeDefaultStringInDifferentCulture2()
        {
            foreach (var culture in CultureInfo.GetCultures(CultureTypes.WindowsOnlyCultures))
            {

                Console.WriteLine(DateTimeFormatInfo.CurrentInfo.FullDateTimePattern);
                Console.WriteLine(DateTime.Now.ToString( DateTimeFormatInfo.InvariantInfo ));
            }
        }
        public static void DateTimeFormatInfoPatternForInvariantInfo()
        {
            Console.WriteLine(DateTime.Now.ToString(DateTimeFormatInfo.InvariantInfo.LongTimePattern, DateTimeFormatInfo.InvariantInfo));
            Console.WriteLine(DateTimeFormatInfo.InvariantInfo.LongTimePattern);
            Console.WriteLine(DateTime.Now.ToString(DateTimeFormatInfo.InvariantInfo.LongDatePattern, DateTimeFormatInfo.InvariantInfo));
            Console.WriteLine(DateTimeFormatInfo.InvariantInfo.LongDatePattern);
            Console.WriteLine(DateTime.Now.ToString(DateTimeFormatInfo.InvariantInfo.ShortDatePattern, DateTimeFormatInfo.InvariantInfo));
            Console.WriteLine(DateTimeFormatInfo.InvariantInfo.ShortDatePattern);
            Console.WriteLine(DateTime.Now.ToString(DateTimeFormatInfo.InvariantInfo.ShortTimePattern, DateTimeFormatInfo.InvariantInfo));
            Console.WriteLine(DateTimeFormatInfo.InvariantInfo.ShortTimePattern);
        }
        #endregion
        #region TwoDigitYearMax
        public static void ShortTimeToLongforError()
        {
            string result = new DateTime(2099, 2, 13).ToString("yy-MM-dd");
            Console.WriteLine(result);
            DateTime time;
            DateTime.TryParse(result, out time);
            Console.WriteLine(time.ToString("yyyy-MM-dd"));
        }
        public static void ShortTimeToLong()
        {
            Thread.CurrentThread.CurrentCulture = new CultureInfo("zh-cn");
            Thread.CurrentThread.CurrentCulture.Calendar.TwoDigitYearMax = 2099;
            Console.WriteLine(CultureInfo.CurrentCulture.Calendar.TwoDigitYearMax);
            string result = new DateTime(2099, 2, 13).ToString("yy-MM-dd");
            Console.WriteLine(result);
            DateTime time;
            DateTime.TryParse(result, out time);
            Console.WriteLine(time.ToString("yyyy-MM-dd"));
        }
        #endregion
        #region 内置的格式化时间 http://msdn.microsoft.com/zh-cn/library/hc4ky857(v=vs.80)
        /// <summary>
        /// 不同culture格式不同 ，格式具有不确定性。
        /// </summary>
        public static void InnerFormatIndifferentCulture()
        {
            Console.WriteLine(DateTime.Now.ToString("d", new CultureInfo("en-US")));
            Console.WriteLine(DateTime.Now.ToString("d", new CultureInfo("de-DE")));
            Console.WriteLine(DateTime.Now.ToString("d", new CultureInfo("en-NZ")));
        }
        #endregion
        #region 自定义字符串格式  http://msdn.microsoft.com/zh-cn/library/hzz3aycd(v=vs.80)
        public static void SelfDefinationFormat()
        {  Console.WriteLine (string.Format ("{0:hh:mm,G\\MT z}",DateTime .Now ));
            Console .WriteLine (DateTime .Now.ToString ("hh:mm, G\\MT zzz"));
            Console .WriteLine (DateTime .Now.ToString ("hh:mm, G\\MT zz"));
            Console .WriteLine (DateTime .Now.ToString ("hh:mm, G\\MT z"));
        }
        #endregion
        #endregion
        #region DateTimeKind .Unspecified==>local or utc
        /// <summary>
        /// 创建一个Unspecified的time
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static DateTime CreatUnspecifiedTime()
        {
            DateTime time = new DateTime(2011, 12, 21);
            return time;
        }
        public static DateTime ConvertUnSpecialTimeToLocal(DateTime time)
        {
            return time.ToLocalTime();
        }
        public static DateTime ConvertUnSpecialTimeToUniversal(DateTime time)
        {
            return time.ToUniversalTime();
        }
        #endregion
        /// <summary>
        /// 修改DateTime值，会创建一个新对象。
        /// </summary>
        public static void CheckDateTime()
        {
            DateTime time = new DateTime(2011, 12, 31);
            Console.WriteLine(time.ToString());
            time.AddMonths(1);
            Console.WriteLine(time.ToString());
        }
    }
}